﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Threading;
using JulMar.Windows.Behaviors;
using JulMar.Windows.Mvvm;
using MediaBrowser.Entities;
using MediaBrowser.Gui.MvvmUtils.UI;
using MediaBrowser.Gui.Tools;
using MediaBrowser.IServices;

namespace MediaBrowser.Gui.ViewModels
{
    /// <summary>
    /// View Model Page Movies
    /// </summary>
    public class PageMoviesViewModel : PageViewModelBase
    {
        private MediaElement mediaElement;
        private DispatcherTimer progressTimer;
        private string currentProgress;
        private string statusPlayer;
        private MediaState CurrentState;
        private IOpenFileDialogVisualizer iOpenFileDialogVisualizer;
        private bool canSave;
        private String statusCanSave;

        public override string Name
        {
            get { return "Page Movies"; }
        }

        #region Properties

        public double TotalDuration
        {
            get
            {
                if (mediaElement != null)
                {
                    if (mediaElement.NaturalDuration.HasTimeSpan)
                    {
                        return mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    return 0;
                }
            }
        }

        public double CurrentPosition
        {
            get
            {
                if (mediaElement != null)
                {
                    return mediaElement.Position.TotalSeconds;
                }
                else
                {
                    return 0;
                }
            }
            set
            {
                mediaElement.Position = new TimeSpan(0, 0, (int)value);
                OnPropertyChanged("CurrentProgress");
            }
        }

        public string CurrentProgress
        {
            get
            {
                return this.currentProgress;
            }
            set
            {
                this.currentProgress = value;
                OnPropertyChanged("CurrentProgress");
            }
        }

        public string StatusPlayer
        {
            get
            {
                return this.statusPlayer;
            }
            set
            {
                this.statusPlayer = value;
                OnPropertyChanged("StatusPlayer");
            }
        }

        public bool CanSave
        {
            get
            {
                return this.canSave;
            }
            set
            {
                this.canSave = value;
                StatusCanSave = String.Empty;
                if (!canSave)
                {
                    StatusCanSave = "Veuillez renseigner tous les champs obligatoire";
                }
                OnPropertyChanged("CanSave");
            }
        }

        public String StatusCanSave
        {
            get
            {
                return this.statusCanSave;
            }
            set
            {
                this.statusCanSave = value;
                OnPropertyChanged("StatusCanSave");
            }
        }

        #endregion

        #region Command

        public ICommand PrepareAddMovieCommand
        {
            get;
            private set;
        }

        public ICommand PrepareUpdateMovieCommand
        {
            get;
            private set;
        }

        public ICommand DropPictureCommand
        {
            get;
            private set;
        }

        public ICommand SaveMovieCommand
        {
            get;
            private set;
        }

        public ICommand DeleteMovieCommand
        {
            get;
            private set;
        }

        public ICommand MediaOpenedCommand
        {
            get;
            private set;
        }

        public ICommand PlayVideoCommand
        {
            get;
            private set;
        }

        public ICommand StopVideoCommand
        {
            get;
            private set;
        }

        public ICommand PauseVideoCommand
        {
            get;
            private set;
        }

        public ICommand MediaFailedCommand
        {
            get;
            private set;
        }

        public ICommand ExploreFileCommand
        {
            get;
            private set;
        }

        public ICommand ClearFileCommand
        {
            get;
            private set;
        }

        #endregion

        public PageMoviesViewModel(IMediaManager service)
            : base(service)
        {
            try
            {
                Medias = new ObservableCollection<Media>(service.ListMediasByCategory(1));
                mediasView = CollectionViewSource.GetDefaultView(Medias);
                if (mediasView != null)
                {
                    mediasView.CurrentChanged += mediasView_CurrentChanged;
                }
                PrepareAddMovieCommand = new DelegatingCommand(PrepareAddMovie);
                PrepareUpdateMovieCommand = new DelegatingCommand(PrepareUpdateMovie);
                DropPictureCommand = new DelegatingCommand<EventParameters>(DropPicture);
                SaveMovieCommand = new DelegatingCommand(SaveMovie);
                DeleteMovieCommand = new DelegatingCommand(DeleteMovie);
                ExploreFileCommand = new DelegatingCommand(ExploreFile);
                ClearFileCommand = new DelegatingCommand(ClearFile);

                MediaOpenedCommand = new DelegatingCommand<object>(MediaOpened);
                MediaFailedCommand = new DelegatingCommand<EventParameters>(MediaFailed);
                PlayVideoCommand = new DelegatingCommand(PlayVideo, CanPlayVideo);
                StopVideoCommand = new DelegatingCommand(StopVideo, CanStopVideo);
                PauseVideoCommand = new DelegatingCommand(PauseVideo, CanPauseVideo);

                this.progressTimer = new DispatcherTimer();
                this.progressTimer.Interval = TimeSpan.FromSeconds(1);
                this.progressTimer.Tick += this.ProgressTimer_Tick;
                CurrentProgress = "00:00:00 / 00:00:00";
                CurrentState = MediaState.Stop;

                iOpenFileDialogVisualizer = Resolve<IOpenFileDialogVisualizer>();
            }
            catch (Exception ex)
            {
                if (icustomMessageBoxVisualizer != null)
                {
                    icustomMessageBoxVisualizer.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Appelé quand le média courant à changé
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void mediasView_CurrentChanged(object sender, System.EventArgs e)
        {
            OnPropertyChanged("CurrentMedia");
            StatusPlayer = String.Empty;
        }

        /// <summary>
        /// Préparation de l'ajout d'un Film
        /// </summary>
        private void PrepareAddMovie()
        {
            CanSave = false;
            if (NewMedia != null)
            {
                NewMedia.PropertyChanged -= NewMedia_PropertyChanged;
            }
            NewMedia = new Media(0, String.Empty, DateTime.Now, null, null, null, null);
            NewMedia.PropertyChanged += NewMedia_PropertyChanged;
        }

        void NewMedia_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            CanSave = true;
            if ((String.IsNullOrEmpty(NewMedia.Name)) ||
                (String.IsNullOrEmpty(NewMedia.Description)) ||
                (String.IsNullOrEmpty(NewMedia.UrlImage)))
            {
                CanSave = false;
            }
        }

        /// <summary>
        /// Préparation de la modification d'un Film
        /// </summary>
        private void PrepareUpdateMovie()
        {
            CanSave = true;
            if (NewMedia != null)
            {
                NewMedia.PropertyChanged -= NewMedia_PropertyChanged;
            }
            NewMedia = (Media)CurrentMedia.Clone();
            NewMedia.PropertyChanged += NewMedia_PropertyChanged;
        }

        /// <summary>
        /// Ajout/Modification Affiche
        /// </summary>
        /// <param name="e"></param>
        private void DropPicture(EventParameters e)
        {
            using (new CustomWaitCursor())
            {
                DragEventArgs de = (DragEventArgs)e.EventArgs;
                string[] fileNames = de.Data.GetData(DataFormats.FileDrop, true) as string[];
                if (fileNames.Length > 0)
                {
                    if (fileNames[0].IsImageFile())
                    {
                        Uri uri = new Uri(fileNames[0], UriKind.RelativeOrAbsolute);
                        NewMedia.UrlImage = uri.LocalPath;
                        OnPropertyChanged("NewMedia");
                    }
                    else
                    {
                        if (icustomMessageBoxVisualizer != null)
                        {
                            icustomMessageBoxVisualizer.Show("Type de fichier inconnu !", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Ajout/Modification d'un Film
        /// </summary>
        private void SaveMovie()
        {
            using (new CustomWaitCursor())
            {
                try
                {
                    #region Ajout
                    if (NewMedia.Id == 0)
                    {
                        Media resultMedia = service.SaveMovie(NewMedia, null);
                        Medias.Add(resultMedia);
                        mediasView.MoveCurrentToLast();
                    }
                    #endregion

                    #region Modification
                    else
                    {
                        var previousMedia = (from m in Medias where m.Id == NewMedia.Id select m).Single<Media>();
                        Media resultMedia = service.SaveMovie(NewMedia, previousMedia);
                        previousMedia.Name = resultMedia.Name;
                        previousMedia.Description = resultMedia.Description;
                        previousMedia.UrlImage = resultMedia.UrlImage;
                        previousMedia.UrlContent = resultMedia.UrlContent;
                        OnPropertyChanged("CurrentMedia");
                        mediasView.Refresh();
                    }
                    #endregion

                }
                catch (Exception ex)
                {
                    if (icustomMessageBoxVisualizer != null)
                    {
                        icustomMessageBoxVisualizer.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
        }

        /// <summary>
        /// Suppression d'un Film
        /// </summary>
        private void DeleteMovie()
        {
            try
            {
                bool continu = true;
                if (icustomMessageBoxVisualizer != null)
                {
                    if (icustomMessageBoxVisualizer.Show("Etes-vous sûr de vouloir supprimer ce Film ?", "Suppression", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.No)
                    {
                        continu = false;
                    }
                }

                if (continu)
                {
                    service.DeleteMovie(CurrentMedia);
                    Medias.Remove(CurrentMedia);
                }

            }
            catch (Exception ex)
            {
                if (icustomMessageBoxVisualizer != null)
                {
                    icustomMessageBoxVisualizer.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

        }

        /// <summary>
        /// Choisir une fichier video associé au Film
        /// </summary>
        private void ExploreFile()
        {
            if (iOpenFileDialogVisualizer != null)
            {
                String result = iOpenFileDialogVisualizer.ShowDialog("*.avi", "Fichier Video (*.avi;*.mpeg;*.mpg;*.mp4;*.mov;*.wmv)|*.avi;*.mpeg;*.mpg;*.mp4;*.mov;*.wmv");
                NewMedia.UrlContent = result;
                OnPropertyChanged("NewMedia");
            }
        }

        /// <summary>
        /// Supprimer le fichier Video
        /// </summary>
        private void ClearFile()
        {
            NewMedia.UrlContent = String.Empty;
            OnPropertyChanged("NewMedia");
        }

        #region Player COMMAND

        /// <summary>
        /// Chargement du Media
        /// </summary>
        /// <param name="param"></param>
        public void MediaOpened(object param)
        {
            MediaElement parmMediaElement = (MediaElement)param;
            mediaElement = parmMediaElement;
            mediaElement.LoadedBehavior = MediaState.Manual;
            mediaElement.UnloadedBehavior = MediaState.Close;
            OnPropertyChanged("TotalDuration");
            StatusPlayer = String.Empty;
        }

        /// <summary>
        /// Exception Chargement du Media
        /// </summary>
        /// <param name="e"></param>
        public void MediaFailed(EventParameters e)
        {
            if (icustomMessageBoxVisualizer != null)
            {
                ExceptionRoutedEventArgs ex = e.EventArgs as ExceptionRoutedEventArgs;

                if (String.IsNullOrEmpty(CurrentMedia.UrlContent))
                {
                    StatusPlayer = "Pas de fichier video pour ce Film !";
                }
                else
                {
                    icustomMessageBoxVisualizer.Show(ex.ErrorException.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        /// <summary>
        /// Progression du Media
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressTimer_Tick(object sender, EventArgs e)
        {
            if (mediaElement.NaturalDuration != Duration.Automatic)
            {
                CurrentProgress = string.Format(
                   "{0}:{1} / {2}:{3}",
                   Math.Floor(mediaElement.Position.TotalMinutes).ToString("00"),
                   mediaElement.Position.Seconds.ToString("00"),
                   Math.Floor(mediaElement.NaturalDuration.TimeSpan.TotalMinutes).ToString("00"),
                   mediaElement.NaturalDuration.TimeSpan.Seconds.ToString("00"));

                OnPropertyChanged("CurrentPosition");
            }
        }

        /// <summary>
        /// Jouer Video
        /// </summary>
        public void PlayVideo()
        {
            mediaElement.Play();
            progressTimer.Start();
            CurrentState = MediaState.Play;
        }

        /// <summary>
        /// Peut-être joué
        /// </summary>
        /// <returns></returns>
        private bool CanPlayVideo()
        {
            bool CanPlay = false;
            if (mediaElement != null)
            {
                if (CurrentState != MediaState.Play)
                {
                    CanPlay = true;
                }
            }
            return CanPlay;
        }

        /// <summary>
        /// Stop la video
        /// </summary>
        public void StopVideo()
        {
            progressTimer.Stop();
            mediaElement.Stop();
            mediaElement.Close();
            CurrentProgress = "00:00:00 / 00:00:00";
            mediaElement.Position = new TimeSpan(0, 0, 0);
            OnPropertyChanged("CurrentPosition");
            CurrentState = MediaState.Stop;
        }

        /// <summary>
        /// Peut-être stoppé
        /// </summary>
        /// <returns></returns>
        private bool CanStopVideo()
        {
            bool CanStop = false;

            if (mediaElement != null)
            {
                CanStop = true;
            }

            return CanStop;
        }

        /// <summary>
        /// Pause Video
        /// </summary>
        public void PauseVideo()
        {
            if (CurrentState == MediaState.Play)
            {
                if (mediaElement.CanPause)
                {
                    mediaElement.Pause();
                }
                else
                {
                    mediaElement.Stop();
                }
                progressTimer.Stop();
                CurrentState = MediaState.Pause;
            }
            else
            {
                mediaElement.Play();
                progressTimer.Start();
                CurrentState = MediaState.Play;
            }
        }

        /// <summary>
        /// Peut-être mise en pause
        /// </summary>
        /// <returns></returns>
        private bool CanPauseVideo()
        {
            bool CanPause = false;

            if (mediaElement != null)
            {
                if ((CurrentState == MediaState.Pause)
                    || (CurrentState == MediaState.Play))
                {
                    CanPause = true;
                }
            }

            return CanPause;
        }

        #endregion


    }
}
